<template>
	<view class="tui-waterfall__box"
		:style="{ paddingLeft: leftGap, paddingRight: rightGap, background: backgroundColor, borderRadius: radius }">
		<view class="tui-waterfall__list" id="tui-waterfall__left" :style="{ marginRight: columnGap }">
			<view v-for="(item, index) in leftList" :key="index">
				<slot name="left" :entity="item" :index="index" :isList="columnCount==1"></slot>
			</view>
		</view>
		<view v-if="columnCount > 1" class="tui-waterfall__list" id="tui-waterfall__right">
			<view v-for="(item, index) in rightList" :key="index">
				<slot name="right" :entity="item" :index="index" :isList="columnCount==1"></slot>
			</view>
		</view>
	</view>
</template>

<script>
	/**
	 * 列表中图片可以使用懒加载或者其他方式
	 * 优先计算出图片高度,以达到最佳效果
	 * App端建议使用weex的waterfall组件，使用案例详见：
	 * [ThorUI组件库->pages->index->productNvue]
	 */
	export default {
		name: 'tuiWaterfall',
		props: {
			//列表数据，不建议一次性加载过多数据
			listData: {
				type: Array,
				default () {
					return [];
				}
			},
			//每页数据条数(固定条数),当总数据长度小于等于该数时表示第一页数据，刷新重置
			pageSize: {
				type: Number,
				default: 10
			},
			//数据分组类型：1-简单左右分组，按顺序排列，伪瀑布流 2-计算左右容器高度进行分组
			type: {
				type: Number,
				default: 1
			},
			//瀑布流列数，目前支持最大值为2
			columnCount: {
				type: Number,
				default: 2
			},
			//列与列的间隙
			columnGap: {
				type: String,
				default: '10rpx'
			},
			//左侧和列表的间隙
			leftGap: {
				type: String,
				default: '0'
			},
			//右侧和列表的间隙
			rightGap: {
				type: String,
				default: '0'
			},
			//列表背景色，可使用渐变色
			backgroundColor: {
				type: String,
				default: 'transparent'
			},
			//列表外层容器圆角值
			radius: {
				type: String,
				default: '0'
			}
		},
		data() {
			return {
				leftListConst: [],
				leftList: [],
				rightList: []
			};
		},
		watch: {
			listData(val) {
				this.columnChange();
			},
			columnCount(val) {
				this.columnChange(val);
			}
		},
		mounted() {
			this.columnChange();
		},
		methods: {
			columnChange(val) {
				if (this.columnCount < 2) {
					this.leftList = [...this.listData];
				} else {
					if (val && val == 2) {
						this.leftList = [...this.leftListConst]
					}
					this.initData()
				}
			},
			initData() {
				if (this.type == 1) {
					this.getSubGroup();
				} else {
					this.getArrayByHeight();
				}
			},
			getDiffList() {
				let diffList = [];
				let total = this.listData.length;
				if (total <= this.pageSize) {
					this.leftListConst = [];
					this.leftList = [];
					this.rightList = [];
				}
				let sum = this.leftListConst.length + this.rightList.length;
				let diff = total - sum;
				if (diff > 0) {
					diffList = [...this.listData].filter((item, index) => {
						return index >= sum;
					});
				}
				return diffList;
			},
			getSubGroup() {
				//type=1时执行简单数据分组
				if (!this.listData && this.listData.length === 0) return;
				let leftList = [];
				let rightList = [];
				let data = this.getDiffList();
				data.forEach((item, index) => {
					if (index % 2 === 0) {
						leftList.push(item);
					} else {
						rightList.push(item);
					}
				});
				this.leftList = this.leftList.concat(leftList);
				this.leftListConst = this.leftListConst.concat(leftList);
				this.rightList = this.rightList.concat(rightList);
			},
			async getArrayByHeight() {
				if (!this.listData && this.listData.length === 0) return;
				let data = this.getDiffList();
				for (let item of data) {
					await this.render(item);
				}
			},
			async render(item) {
				let obj = await this.getContainerHeight();
				return await new Promise((resolve, reject) => {
					if (obj && typeof obj.leftHeight === 'number') {
						if (obj.leftHeight <= obj.rightHeight) {
							this.leftList.push(item);
							this.leftListConst.push(item);
						} else {
							this.rightList.push(item);
						}
						this.$nextTick(() => {
							setTimeout(() => {
								resolve(true);
							}, 50);
						});
					} else {
						reject(false);
					}
				});
			},
			async getContainerHeight() {
				//type=2
				return await new Promise((resolve, reject) => {
					const query = uni.createSelectorQuery().in(this);
					let nodes = query.selectAll('#tui-waterfall__left, #tui-waterfall__right');
					nodes.boundingClientRect().exec(res => {
						if (res && res[0]) {
							const rects = res[0];
							const leftHeight = rects[0].height;
							const rightHeight = rects[1].height;
							resolve({
								leftHeight: leftHeight,
								rightHeight: rightHeight
							});
						} else {
							reject(res);
						}
					});
				});
			}
		}
	};
</script>

<style scoped>
	.tui-waterfall__box {
		width: 100%;
		display: inline-flex;
		justify-content: space-between;
		flex-direction: row;
		flex-wrap: wrap;
		box-sizing: border-box;
		align-items: flex-start;
	}

	.tui-waterfall__list {
		flex: 1;
	}
</style>
